import { FileUploadHelper } from "@shared/helpers/FileUploadHelper";
import { HtmlHelper } from "@shared/helpers/HtmlHelper";
import { ClipboardService } from "./clipboard.service";
import { ILayoutEditor } from "./ILayout-editor";
import { LayoutStyles } from "./layout-content-style";
import { HeadingData, LayoutEditorHelper } from "./layout-editor-helper";

export type LayoutElementType = 'Canvas' | 'Grid' | 'Row' | 'Column' | 'Content';
export type LayoutContentType = 'Canvas' | 'Grid' | 'Row' | 'Column' | 'Html' | 'Text' | 'Image' | 'Heading' | 'Divider'| 'Video';

export class LayoutElement{

    constructor(type:LayoutElementType, contentTypeLabel:LayoutContentType){
        this.type = type;
        this.contentTypeLabel = contentTypeLabel;

        this.children = [];
        this.id =  'i' +FileUploadHelper.randomId();

        if (this.contentTypeLabel === "Image"
            || this.contentTypeLabel === "Video"
            || this.contentTypeLabel === "Divider"
            || this.contentTypeLabel === "Heading") {
            this.isSingleContentElement = true;
        }
    }

    type : LayoutElementType;

    //前台输出时，element上添加的属性
    //htmlClass: string = '';
    htmlMobileStyle: LayoutStyles = null;
    htmlStyle: LayoutStyles = null;


    isTemplated: boolean = false;

    /// <summary>
    /// 暂未使用
    /// </summary>
    ///rule: string= "";

    width:number = 12;

    children:LayoutElement[] = []

    hasEditor: boolean = false;

    contentTypeLabel:LayoutContentType ;

    html: string = '';
    data : string = '';

    //--下面的不需要持久化--
    parent: LayoutElement = null;
    id : string ;

    isSelected:boolean = false;  //下级某一个元素被选中

    isFocused:boolean = false;
    isActive:boolean = false;

    isDropTarget:boolean = false;

    isDropingItem:boolean = false;

    isSingleContentElement = false;

    headingData : HeadingData;

    editor: ILayoutEditor;

    templateStyles:{[key:string]:string} ={};
    templateMobileStyles:{[key:string]:string} ={};

    get allowedChildTypes():LayoutElementType [] {
        if(this.type === "Canvas"){
            return  ["Grid", "Content", "Canvas"];
        }
        
        if(this.type === "Grid"){
            return  ["Row"];
        }
        
        if(this.type === "Row"){
            return  ["Column"];
        }

        if(this.type === "Column"){
            return  ["Content", "Grid" ,"Canvas"];
        }

        return [];
    }
    get allowedChildLabels():LayoutContentType [] {
        if(this.type === "Canvas"){
            return  ['Html' , 'Image' , 'Video' , 'Heading', 'Divider', "Grid",  "Canvas"]; //'Text' ,
        }
        
        if(this.type === "Grid"){
            return  ["Row"];
        }
        
        if(this.type === "Row"){
            return  ["Column"];
        }

        if(this.type === "Column"){
            return  [ 'Html' ,  'Image' , 'Video', 'Heading', 'Divider', "Grid", "Canvas"];//'Text' ,
        }

        return [];
    }

    get isContainer(): boolean{
        return this.type !== "Content";
    }

    //设为模版，不可编辑
    setIsTemplated(value: boolean) {
        this.isTemplated = value;
        this.children.forEach(t=> t.setIsTemplated(value));
        this.updateChange();
    }

    private updateChange(){
        this.editor.dataChange.emit(this.editor.data);
    }

    toObject(){
        return new LayoutElementCheck(this);
    }

    //?
    isSealed(){
        return this.children.findIndex(t=> t.isTemplated) > -1;
    }

    canAddColumn(newColumnWidth:number){
        if(this.type === "Row"){
            let sum = 0;
            this.children.forEach(t=> {sum = sum + t.width});

            if(sum >= 12){
                return false;
            }
            if(sum + newColumnWidth > 12){
                return false;
            }
            return true;
        }
        return false;
    }

    getClasses() {
        let result = ['layout-element'];
        if (this.type != "Content") {
            result.push("layout-container");
            if (this.isSealed())
                result.push("layout-container-sealed");
        }

        result.push("layout-" + this.type.toLowerCase());

        //if (!!this.dropTargetClass)
        //result.push(this.dropTargetClass);

        if (this.type == "Row") {
            if (!this.canAddColumn(0)) {
                result.push("layout-row-full");
            }
        } else if (this.type === "Column") {
            result.push("col-md-" + this.width);
        } else if (this.type === "Content") {
            if (!this.isDropingItem) {
                if (this.contentTypeLabel === "Html") {
                    result.push("layout-content-h-t-m-l");
                } else if (this.contentTypeLabel === "Text") {
                    result.push("layout-content-text");
                } else if (this.contentTypeLabel === "Divider") {
                    result.push("layout-content-break");
                } else if (this.contentTypeLabel === "Heading") {
                    result.push("layout-content-heading-h1-h6");
                } else if (this.contentTypeLabel === "Image") {
                    result.push("layout-content-image");
                } else if (this.contentTypeLabel === "Video") {
                    result.push("layout-content-video");
                }
            }
        }

        if (this.isFocused) {
            result.push("layout-element-focused");
        }
        if (this.isSelected) {
            result.push("layout-element-selected");
        }
        if (this.isActive) {
            result.push("layout-element-active");
        }
        if (this.isDropTarget) {
            result.push("layout-element-droptarget");
        }
        if (this.isTemplated) {
            result.push("layout-element-templated");
        }
        if (this.isDropingItem) {
            result.push("ui-sortable-placeholder");
        }

        return result.join(' ');
    }

    getChildrenWrapperClasses(){
        let result = [];
        if(this.type ==="Row"){
            result.push("row"); 
        }
        if(this.editor.isDragging || this.editor.isEditing){
            result.push("layout-editing"); 
        }
        if(this.isSelected){
            result.push("layout-editing"); 
        }

        return result.join(' ');
    }

    
    getShowChildrenPlaceholder() {
        if(this.children.length === 0 && !this.isDropTarget){
            return true;
        }
        return false;
    }

    getPlaceHolder(){
        if(this.type === "Canvas"){
            return "Drag an element from the toolbox and drop it here to add content."
        }
        
        if(this.type === "Grid"){
            return "Drag a row element from the toolbox and drop it here to add a row."
        }
        
        if(this.type === "Row"){
            return "Drag a column element from the toolbox and drop it here to add a column."
        }
        
        if(this.type === "Column"){
            return "Drag an element from the toolbox and drop it here to add content."
        }

        return '';
    }

    
    getPanelLabel(){
        if(this.type ==="Column"){
            return this.type +' ('+ this.width +')';
        }
        
        if(this.type === "Content"){
            if(this.contentTypeLabel === "Html"){
                return "Text";
            }
            return this.contentTypeLabel
        }

        return this.type;
    }

    canDelete():boolean{
        if (this.isTemplated || !this.parent){
            return false;
        }
        return true;
    }
    delete(){
        if (!this.canDelete())
            return;

        this.parent.deleteChild(this);    
        
        this.updateChange();
    }
    canMoveUp():boolean{
        if (this.isTemplated)
        {
            return false;
        }

        if(this.parent){
            let index = this.parent.children.findIndex(t=>t.id === this.id);
            if(index === 0){
                return false;
            }
            return true;
        }
        return false;
    }

    canMoveDown():boolean{
        if (this.isTemplated)
        {
            return false;
        }
        
        if(this.parent){
            let index = this.parent.children.findIndex(t=>t.id === this.id);
            if(index === this.parent.children.length - 1){
                return false;
            }
            return true;
        }
        return false;
    }   
    moveUp(){
        if (!this.canMoveUp())
        {
            return false;
        }

        let index = this.parent.children.findIndex(t=>t.id === this.id);
        if(index === 0){
            return;
        }
        
        let preIndex = index - 1 ;
        let temp = this.parent.children[index];
        this.parent.children[index] = this.parent.children[preIndex];
        this.parent.children[preIndex] = temp;
        
        this.updateChange();
    }

    moveDown(){
        if (!this.canMoveDown())
        {
            return false;
        }

        let index = this.parent.children.findIndex(t=>t.id === this.id);
        if(index === this.parent.children.length - 1){
            return ;
        }

        let nextIndex = index + 1 ;
        let temp = this.parent.children[index];
        this.parent.children[index] = this.parent.children[nextIndex];
        this.parent.children[nextIndex] = temp;

        this.updateChange();
    } 

    cansplitColumn():boolean{
        if (this.isTemplated)
        {
            return false;
        }

        if(this.type === "Column" && this.width > 1){
            return true;
        }
        return false;
    }    

    splitColumn(){
        if (!this.cansplitColumn())
        {
            return false;
        }

        let newColumnWidth = Math.floor(this.width / 2);
        let newColumn = new LayoutElement('Column', 'Column');
        newColumn.width = newColumnWidth;
        this.width = this.width - newColumnWidth;

        this.parent.insertChild(newColumn, this);
        newColumn.setIsFocused();
        this.updateChange();
    }

    canDecreaseColumnWidth():boolean{
        if (this.isTemplated)
        {
            return false;
        }
        if(this.type === "Column" && this.width > 1){
            return true;
        }
        return false;
    }    

    decreaseColumnWidth(){
        if (!this.canDecreaseColumnWidth())
        {
            return false;
        }
        this.width = this.width - 1;
        this.updateChange();
    }
    canIncreaseColumnWidth():boolean{
        if (this.isTemplated)
        {
            return false;
        }
        if(this.type === "Column"){
            if(this.parent.canAddColumn(1)){
                return true;
            }
        }
        return false;
    }    

    increaseColumnWidth(){
        if (!this.canIncreaseColumnWidth())
        {
            return false;
        }
        this.width = this.width + 1;
        this.updateChange();
    }
    canSelectParent():boolean{
        if(this.parent){
            return true;
        }
    }    

    selectParent(){
        if (!this.canSelectParent())
        {
            return false;
        }
        this.parent.setIsFocused();
    }
    canSelectFirstChild():boolean{
        if(this.children.length > 0){
            return true;
        }
    }    

    selectFirstChild(){
        if (!this.canSelectFirstChild())
        {
            return false;
        }
        this.children[0].setIsFocused();
    }


    unDelete(){
        if(this.editor.recycleBin && this.editor.recycleBin.length > 0 ){
            let item = this.editor.recycleBin.pop();
            item.parent.addToChildren(item);
            item.setIsFocused();
        }
        
        this.updateChange();
    }

    addToChildren(child:LayoutElement){
        if(this.children.findIndex(t=> t.id === child.id) > -1){
            return;
        }

        if(this.allowedChildTypes.findIndex(t=> t== child.type) === -1){
            return;
        }

        // if(this.type === "Row" && child.type === "Column" && !this.canAddColumn(child.width)){
        //     return;
        // }
        if(child.parent){
            child.parent.children =  child.parent.children.filter(tt=> tt.id !== child.id);
        }
        child.parent = this;
        child.editor = this.editor;
        this.children.push(child);
    }
    
    deleteChild(child:LayoutElement){
        let index = this.children.findIndex(t=>t.id === child.id);
        if (index >= 0) {
            this.children.splice(index, 1);
            this.editor.recycleBin.push(child);

            if(child.isFocused){
                if (this.children.length > index)
                this.children[index].setIsFocused();
            else if (index > 0)
                this.children[index - 1].setIsFocused();
            else
                this.setIsFocused();
            }
        }
    }

    setIsFocused(){
        LayoutElement.alterAlongTree(this.editor.eleData, (t) => {
            if(t.id !== this.id){
                t.isSelected = false;
                t.isFocused = false;
            }
        });

        this.isSelected = true;
        this.isFocused = true;
        
        let parent = this.parent;
        while(parent){
            parent.isSelected = true;
            parent = parent.parent;
        }

        this.editor.focusedElement = this;
    }

    moveFocusPrevChild(child) {
        if (this.children.length < 2)
            return;
        let index = this.children.findIndex(t=>t.id === child.id);
        if (index > 0)
            this.children[index - 1].setIsFocused();
    }

    moveFocusNextChild(child) {
        if (this.children.length < 2)
            return;
        let index = this.children.findIndex(t=>t.id === child.id);
        if (index < this.children.length - 1)
            this.children[index + 1].setIsFocused();
    }

    insertChild(child, afterChild) {
        let index = this.children.findIndex(t=>t.id === child.id);
        if (index < 0) {
            let afterIndex = this.children.findIndex(t=>t.id === afterChild.id);
            index = Math.max(afterIndex, 0);
            if(child.parent){
                child.parent.children =  child.parent.children.filter(tt=> tt.id !== child.id);
            }
            this.children.splice(index + 1, 0, child);

            child.parent = this;
            child.editor = this.editor;
        }
    }
    insertChildByReplaceIndex(child, replaceChild, offsetIndex:number) {
        let index = this.children.findIndex(t=>t.id === child.id);
        if (index < 0) {
            let afterIndex = this.children.findIndex(t=>t.id === replaceChild.id);
            index = Math.max(afterIndex, 0);
            index = index + offsetIndex;
            if(child.parent){
                child.parent.children =  child.parent.children.filter(tt=> tt.id !== child.id);
            }
            this.children.splice(index, 0, child);

            child.parent = this;
            child.editor = this.editor;
        }else{
            let afterIndex = this.children.findIndex(t=>t.id === replaceChild.id);
            let newIndex = Math.max(afterIndex, 0);
            if(newIndex > index){
                newIndex--;
            }

            newIndex = newIndex + offsetIndex;
            // // 需要取坐标，确认是替换当前位置还是添加到它的后面
            if(newIndex !== index){
                let temp = this.children[index];
                this.children[index] = this.children[newIndex];
                this.children[newIndex] = temp;
            }
        }
    }

    copy(clipboardData:ClipboardService) {
        let data = this.toObject();
        let json = JSON.stringify(data, null, "\t");
        //clipboardData.setData("json", json);

        clipboardData.setData(json)
    }

    cut(clipboardData:ClipboardService) {
        if (this.canDelete()) {
            this.copy(clipboardData);
            this.delete();
        }

        this.updateChange();
    }

    paste(clipboardData:ClipboardService){
        let clipdata = clipboardData.getData();
        if(clipdata){
            let data = JSON.parse(clipdata);
            let child = LayoutElement.fromJs(data, this.editor);
            
            this.pasteChild(child);
        }

        this.updateChange();
    }
    private pasteChild(child: LayoutElement){
        if(this.allowedChildTypes.findIndex(t=> t== child.type) >= 0){
            this.addToChildren(child);
        }else if(this.parent){
            this.parent.pasteChild(child);
        }
    }
    insertRecursively(child, offsetIndex:number) :LayoutElement{
        if(this.allowedChildTypes.findIndex(t=> t== child.type) >= 0){
            // 直接拖进了当前元素，意味着它其实没有下级（padding先忽略）
            this.addToChildren(child);
            return this;
        }else if(this.parent){
            return this.parent.insertChilidRecursively(child, this, offsetIndex);
        }
    }
    private insertChilidRecursively(child: LayoutElement, replaceIndex: LayoutElement, offsetIndex:number):LayoutElement{
        if(this.allowedChildTypes.findIndex(t=> t== child.type) >= 0){
           this.insertChildByReplaceIndex(child, replaceIndex, offsetIndex);
           return this;
        }else if(this.parent){
            return this.parent.insertChilidRecursively(child, this, offsetIndex);
        }
    }
    
    // 更新编辑数据
    setItemData(data: string){
        if (this.contentTypeLabel === "Html") {
            this.data = HtmlHelper.htmlEncode(data);
            return;
        } 
        
        if (this.contentTypeLabel === "Text") {
            this.data = data;
            return;
        } 
        
        if (this.contentTypeLabel === "Divider") {
            this.data = HtmlHelper.htmlEncode("<hr>");
            return;
        } 
        
        if (this.contentTypeLabel === "Heading") {
            this.data = data;
            return;
        } 
        
        if (this.contentTypeLabel === "Image") {
            this.data = data;
            return;
        }

        if (this.contentTypeLabel === "Video") {
            this.data = data;
            return;
        }
    }

    // 更新html, 用于前后台的页面呈现
    setItemHtml(){
        if(this.type !== "Content"){
            return;
        }
        let defaultLineHeight = "0.875em";
        
        let style = this.getHtmlTemplateStyles();
        if (this.contentTypeLabel === "Html") {
            let html = HtmlHelper.htmlDecode(this.data);
            if(!style.lineHeight){
                style.lineHeight = defaultLineHeight;
            }
            let css = this.styleKeyValueToCssString(style);
            if(css){
                this.html = "<div style=\""+ css +"\">" + HtmlHelper.getInputHtml(html) + "</div>";
            }else{
                this.html = "<div>" + HtmlHelper.getInputHtml(html) + "</div>"; 
            }

            return;
        } 
        
        if (this.contentTypeLabel === "Text") {
            if(!style.lineHeight){
                style.lineHeight = defaultLineHeight;
            }
            let css = this.styleKeyValueToCssString(style);
            if(css){
                this.html = "<div style=\""+ css +"\">" + this.data + "</div>";
            }else{
                this.html = "<div>" + this.data + "</div>"; 
            }

            return;
        } 
        
        if (this.contentTypeLabel === "Divider") {
            let css = this.styleKeyValueToCssString(style);
            if(css){
                this.html = "<hr style=\""+ css +"\" />";
            }else{
                this.html = "<hr/>";
            }

            return;
        } 
        
        if (this.contentTypeLabel === "Heading") {
            if(this.data){
                LayoutEditorHelper.setHeadingData(this);
                let json = LayoutEditorHelper.headingDataToJson(this);
                if(!style.lineHeight){
                    style.lineHeight = defaultLineHeight;
                }    
                let css = this.styleKeyValueToCssString(style);
                if(css){
                    this.html = "<h"+json.h +" style=\""+ css +"\">"+json.data+"</h"+json.h +">";
                }else{
                    this.html = "<h"+json.h +">"+json.data+"</h"+json.h +">";
                }
            }
      
           
            return;
        } 
        
        if (this.contentTypeLabel === "Image") {
            if (this.data) {
                let html: string;
                let align : string;
                if(this.htmlStyle){
                    align = this.htmlStyle.textAlign.toString();
                 }else{
                    align = "text-align:center";
                    style.width= "100%;"
                }

                let css = this.styleKeyValueToCssString(style);
                html = "<div style=\"position:relative;line-height:0px;"+align+"\"><img style=\""+ css +"\" alt=\"\" src=\"" + this.data + "\"></div>";
    
                this.html = HtmlHelper.getInputHtml(html);
            } else {
                this.html = '';
            }
            return;
        }

        if (this.contentTypeLabel === "Video") {
            if (this.data) {
                let html : string;
                let align : string;
                if(this.htmlStyle){
                    align = this.htmlStyle.textAlign.toString();
                }else{
                    align = "text-align:center";
                    style.width= "100%;"
                }

                let css = this.styleKeyValueToCssString(style);

                html = "<div class=\"video-box\" style=\"position:relative;line-height:0;"+ align + "\" >";
                html += "	<video class=\"video-js vjs-default-skin vjs-big-play-centered\" controls=\"\" data-setup=\"{}\" playsinline=\"true\"  ";
                html += "	    style=\""+ css +"\" webkit-playsinline=\"true\" preload=\"auto\" ";
                html += "	   x-webkit-airplay=\"allow\" x5-video-player-type=\"h5\">";
                html += "		<source src=\"" + this.data + "\" type=\"video/mp4\" />";
                html += "	<p class=\"vjs-no-js\">To view this video please enable JavaScript, and consider upgrading to a web browser that<a href=\"http://videojs.com/html5-video-support/\" target=\"_blank\">supports HTML5 video</a></p>";
                html += "	</video>";
                html += "</div>";
    
                this.html = HtmlHelper.getInputHtml(html);
            } else {
                this.html = '';
            }
            return;
        }
    }

    setTemplateStyles(){
        if(this.htmlStyle){
            this.templateStyles = this.htmlStyle.toArray(this.contentTypeLabel);
        }else{
            let default1 = LayoutEditorHelper.getDefaultStyleValue(this, false)
            this.templateStyles = default1.toArray(this.contentTypeLabel);;
        }
        if(this.htmlMobileStyle){
            this.templateMobileStyles = this.htmlMobileStyle.toArray(this.contentTypeLabel);
        }else{
            let default2 = LayoutEditorHelper.getDefaultStyleValue(this, true)
            this.templateMobileStyles = default2.toArray(this.contentTypeLabel);;
        }
    }

    private styleKeyValueToCssString(styles: {[key:string]:string}): string{
        let css = "";
        styles = styles || {};
        for (let property in styles) {
            css += property + ":" + styles[property] + ";";
        }
        return css;
    }

    private getHtmlTemplateStyles() :{[key:string]:string} {
        let css:{[key:string]:string} = {};

        let styles = this.templateStyles || {};
        for (let property in styles) {
            css[property] = styles[property];
        }

        return css;
    }

    // 容器的自定义样式
    getNgStyles():{[key:string]:string} {
        let css:{[key:string]:string} = {};

        if(this.editor.isDragging || this.editor.isEditing){
            let styles = this.templateStyles || {};
            for (let property in styles) {
                if(property !== 'padding'){
                    css[property] = styles[property];
                }
            }
        }else{
            let styles = this.templateStyles || {};
            for (let property in styles) {
                css[property] = styles[property];
            }
        }

        return css; 
    }

    canEdit(){
        return this.type ==='Content'&& this.contentTypeLabel !== 'Divider';
    }

    static alterAlongTree(item: LayoutElement,action: (t: LayoutElement)=>void){
        action(item);
        item.children.forEach(t=> {this.alterAlongTree(t, action)});
    }

    static GetDefaultData(editor:ILayoutEditor) {
        let root = new LayoutElement('Canvas', 'Canvas');
        root.editor = editor;
        
        return root;
    }
    static fromJs(json:any, editor:ILayoutEditor):LayoutElement{
        try {
            json = typeof json === 'object' ? json : {};

            let type = json["type"];
            if (!type) {
                return LayoutElement.GetDefaultData(editor);
            }

            let contentTypeLabel = json["contentTypeLabel"];
            let root = new LayoutElement(type, contentTypeLabel);
            root.editor = editor;

            root.init(editor, json);

            return root;
        } catch (e) {
            console.log(e);
            return LayoutElement.GetDefaultData(editor);
        }
    }

    init(editor:ILayoutEditor,_data?: any, parent?:LayoutElement) {
        if (_data) {

            //this.htmlClass = _data["htmlClass"];

            //this.rule = _data["rule"];

            this.width = _data["width"];
            this.contentTypeLabel = _data["contentTypeLabel"];
            this.data = _data["data"];
            this.isTemplated = _data["isTemplated"];
            this.hasEditor = _data["hasEditor"];

            if(_data["htmlMobileStyle"]){
                this.htmlMobileStyle = LayoutStyles.fromJs(_data["htmlMobileStyle"]);
            }
            if(_data["htmlStyle"]){
                this.htmlStyle = LayoutStyles.fromJs(_data["htmlStyle"]);
            }
            this.setTemplateStyles();

            this.setItemHtml();

            if (Array.isArray(_data["children"])) {
                this.children = [] as any;
                for (let item of _data["children"]){
                    let child = LayoutElement.fromJs(item, editor);
                    child.parent = this;
                    child.editor = this.editor;
                    this.children!.push(child);
                }
            }
        }
    }
}

export class LayoutElementCheck{

    constructor(ele:LayoutElement){
        this.ToLayoutElementCheck(ele, this);
    }

    private ToLayoutElementCheck(ele:LayoutElement, eleCheck: LayoutElementCheck){
        if(ele){
            eleCheck.type = ele.type;
            //eleCheck.htmlClass = ele.htmlClass;

            let tempPc = LayoutEditorHelper.getDefaultStyleStringValue(ele, false);
            if(JSON.stringify(ele.htmlStyle) === tempPc){
                eleCheck.htmlStyle = null;
            }else{
                eleCheck.htmlStyle = ele.htmlStyle;
            }

            let tempMobile = LayoutEditorHelper.getDefaultStyleStringValue(ele, true);
            if(JSON.stringify(ele.htmlMobileStyle) === tempMobile){
                eleCheck.htmlMobileStyle = null;
            }else{
                eleCheck.htmlMobileStyle = ele.htmlMobileStyle;
            }
    
            //eleCheck.rule = ele.rule;
            eleCheck.width = ele.width;
    
            eleCheck.contentTypeLabel = ele.contentTypeLabel;
            eleCheck.data = ele.data;
            eleCheck.isTemplated = ele.isTemplated;
            eleCheck.hasEditor = ele.hasEditor;
    
            eleCheck.children = [];

            for (let item of ele.children){
                if(!item.isDropingItem){
                    let t = new LayoutElementCheck(item);
                    eleCheck.children.push(t);
                }
            }
        }
    }

    type : LayoutElementType;

    //前台输出时，element上添加的属性(目前未提供编辑)
    //htmlClass: string = "";
    htmlMobileStyle: LayoutStyles = null;
    htmlStyle: LayoutStyles = null;

    /// <summary>
    /// 自定义的一些其他的html属性(目前未使用)
    /// </summary>
    rule: string= "";

    width:number = 12;

    children:LayoutElementCheck[] = []

    contentTypeLabel:LayoutContentType ;

    html: string;
    data : string;

    // 模版不可编辑
    isTemplated : boolean = false;

    hasEditor: boolean = false;
}